package com.xxxx.reflection;

import com.xxxx.reflection.annotation.Autowired;
import com.xxxx.reflection.annotation.Bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Container {
    private Map<Class<?>, Method> map;   // 储存的是 加@Bean注解的方法

    private Map<Class<?>, Object> instanceMap;  // 实现单例
    private Object config;

    public void init() throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException {
        map = new HashMap<>();
        instanceMap = new HashMap<>();
        Class<?> aClass = Class.forName("com.xxxx.reflection.Config");
        // 获取全部方法(私有 公有)
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            // 获取注解 如果@Bean 不为空
            if (method.getAnnotation(Bean.class) != null)
                // key为方法类型 value 为方法本身
                this.map.put(method.getReturnType(), method);  // 拿到所有生成对象的方法
        }
        // 通过构造方法生成对象实例
        this.config = aClass.getConstructor().newInstance(); // 获得可以调用 map 集合方法生成实例的对象

    }

    // 根据对象的class类型 获取构造方法实例 的每个参数类型
    public Object getServiceInstanceByClass(Class<?> clazz) throws InvocationTargetException, IllegalAccessException {
        if (this.map.containsKey(clazz)) {
            if (!this.instanceMap.containsKey(clazz)) {
                Method method = map.get(clazz);
                Object instance = method.invoke(config);
                this.instanceMap.put(clazz, instance);
            }
            return this.instanceMap.get(clazz);
        }
        return null;
    }

    public Object createInstance(Class<?> clazz) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
        // 构造方法集合,无参与有参都会加入  (构造方法 哪个写在前面,哪个就在前面)
        Constructor<?>[] constructors = clazz.getConstructors();
        // 获取该class的全部构造方法进行遍历
        for (Constructor<?> constructor : constructors) {
            // 如果该构造方法 具有 @Autowired
            if (constructor.getAnnotation(Autowired.class) != null) {
                Class<?>[] parameterTypes = constructor.getParameterTypes();
                System.out.println(parameterTypes.length);
                System.out.println(Arrays.toString(parameterTypes));
                Object[] argument = new Object[parameterTypes.length];
                for (int i = 0; i < argument.length; i++) {
                    argument[i] = getServiceInstanceByClass(parameterTypes[i]);
                }
                return constructor.newInstance(argument);
            }
        }
        return clazz.getConstructor().newInstance();
    }


}
